//
//  UIManager.m
//  Voxper
//
//  Created by Erphan on 2/7/11.
//  Copyright 2011 Smonte. All rights reserved.
//

#import "UIManager.h"
#import "VoxperAppDelegate.h"
#import "SipCallInfo.h"
#import "Constants.h"
#import "Settings.h"
#import "DatabaseManager.h"
#import "WebProxy.h"
#import "RequestData.h"
#import "Country.h"
#import "PhoneContact.h"
#import "SipAccountInfo.h"
#import "JSON.h"
#import "Base64.h"
#import "CallInProgressViewController.h"
#import "RecentCallItem.h"
#import "RegexKitLite.h"
#import "ABRecordReader.h"
#import "ABContactsHelper.h"
#import "ConversationItem.h"
#import "SplashViewController.h"
#import "RegistrationOptionsViewController.h"
#import <AddressBook/AddressBook.h>

@interface UIManager(Private)
- (void)workOnLocationResponse:(NSString *)responseString;
- (void)workOnRegisterResponse:(NSString *)responseString :(NSString *)result;
- (void)workOnPasscodeResponse:(NSString *)responseString :(NSString *)result;
- (void)workOnSendTextResponse:(NSString *)responseString :(NSString *)result;
- (void)workOnGetTextMessagesResponse:(NSString *)responseString :(NSString *)result;
- (void)workOnRegisteredContactsResponse:(NSString *)responseString :(NSString *)result;
- (void)workOnRecentCallsResponse:(NSString *)responseString :(NSString *)result;

- (void)loadContacts;
- (void)getContactsFromDatabase;
- (void)getConversationsFromDatabase:(BOOL)bSilently;
- (void)getRegisteredContactsFromServer;
- (void)loadRecentCalls;
- (void)getTextMessagesFromServer:(NSString *)pageNumber;
- (void)markConversationAsRead:(id)fromPhone;
- (void)addRecentCallAndReload:(RecentCallItem *)recentCallItem;
- (void)deleteConversationFromServer:(NSString *)strPhoneNumber;
@end


@implementation UIManager

@synthesize settings;
@synthesize dbManager;

- (id)init {
    self = [super init];
	if (self) {
		app = (VoxperAppDelegate *)[[UIApplication sharedApplication] delegate];
		settings = [[Settings alloc] init];
		dbManager = [[DatabaseManager alloc] init];
		proxy = [[WebProxy alloc] init];
		m_bCallingUILaunched = NO;
		m_bContactListSent = NO;
	}
	return self;
}

- (void)dealloc {
	
	if (countries) {
		[countries release];
	}
	[contacts release];
    [m_Conversations release];
	[proxy release];
	[dbManager release];
	[settings release];
	[super dealloc];
}

- (void)launchAnswerScreen:(NSString *)initalContactName {
	CallInProgressViewController *callinprogressController = [[CallInProgressViewController alloc] initWithNibName:@"CallInProgressViewController" bundle:[NSBundle mainBundle]];
	callinprogressController.PushInvoked = YES;
	callinprogressController.InitalContactName = initalContactName;
	[app.NavigationController presentModalViewController:callinprogressController animated:YES];
	[callinprogressController release];
	m_bCallingUILaunched = YES;
}

- (void)handleCallStateChangedNotification:(NSNotification *)note {
	NSDictionary *dic = (NSDictionary *)[note userInfo];
	SipCallInfo *callInfo = (SipCallInfo *)[dic objectForKey:DIC_CALLINFO];

	dispatch_async(dispatch_get_main_queue(), ^{
		switch(callInfo.state) {
			case 1:
			case 2:
			{
                NSLog(@"UIManager: HandleCallStateChangedNotification -> invoking view controller");
				CallInProgressViewController *callinprogressController = [[CallInProgressViewController alloc] initWithNibName:@"CallInProgressViewController" bundle:nil];
				[app.NavigationController presentModalViewController:callinprogressController animated:YES];
				[callinprogressController release];
				m_bCallingUILaunched = YES;
                
				m_RecentCall = [[RecentCallItem alloc] init];
				m_RecentCall.CallTime = [[NSDate date] timeIntervalSince1970];
				m_RecentCall.CallType = 1;
                if (callInfo.state == 1) {
                    m_RecentCall.CallType = 0;
                }
				m_RecentCall.Duration = 0;
				break;
			}
			case 3:
				break;
            case 5:
                // call is connected now mark the missed call an incoming call
                if (m_RecentCall && m_RecentCall.CallType == 1) {
                    m_RecentCall.CallType = 2;
                }
                break;
			case 6:
				if (m_RecentCall && callInfo && [callInfo remoteInfo]) {
					m_RecentCall.PhoneNumber = [callInfo remoteInfo];
					m_RecentCall.Duration = callInfo.connectionDuration;
					[self performSelectorInBackground:@selector(addRecentCallAndReload:) withObject:m_RecentCall];
				}
				[m_RecentCall release];
				m_bCallingUILaunched = NO;
				break;
			default:
				break;
		}
		[[NSNotificationCenter defaultCenter] postNotificationName:@"CallStateNotification" object:[note object] userInfo:[note userInfo]];
	});
}

- (void)handleRegistrationStateChangedNotification:(NSNotification *)note {
	NSDictionary *dic = (NSDictionary *)[note userInfo];
	SipAccountInfo *accInfo = (SipAccountInfo *)[dic objectForKey:DIC_ACCOUNTINFO];
	NSLog(@"UIManager.RegistrationCallback.Account.Status: %d", [accInfo.status intValue]);
	
	if ([accInfo.status intValue] == 200) {
		dispatch_async(dispatch_get_main_queue(), ^{
			[[NSNotificationCenter defaultCenter] postNotificationName:@"SipRegistration" object:@"OK" userInfo:nil];
		});
	} else {
		m_bCallingUILaunched = NO;
		dispatch_async(dispatch_get_main_queue(), ^{
			[[NSNotificationCenter defaultCenter] postNotificationName:@"SipRegistration" object:@"FAILED" userInfo:nil];
		});
	}
}

- (NSMutableArray *)countriesList {
	if (!countries) {
		countries = [[NSMutableArray alloc] init];
		if ([dbManager getCountriesList:countries] == NO) {
			NSLog(@"UIManager -> getCountriesList -> NO");
		}
	}
	return countries;
}

- (NSMutableArray *)getContacts {
	if (!contacts) {
		contacts = [[NSMutableArray alloc] init];
		[self performSelectorInBackground:@selector(loadContacts) withObject:nil];
	}

	return contacts;
}

- (BOOL)getSipContacts:(NSString *)strLocalId destinationArray:(NSMutableArray *)destinationArray {
	return [dbManager getSipContacts:strLocalId destinationArray:destinationArray];
}

- (void)deleteConversationsAtIndexPaths:(NSArray *)indexPaths {
    for (int i = 0; i < [indexPaths count]; i++) {
        ConversationItem *conversationItem = [m_Conversations objectAtIndex:[[indexPaths objectAtIndex:i] row]];
        if ([dbManager deleteConversationFromNumber:conversationItem.FromPhone]) {
            [self deleteConversationFromServer:conversationItem.FromPhone];
        }
        
        [m_Conversations removeObjectAtIndex:[[indexPaths objectAtIndex:i] row]];
    }
    
    //int nUnreadCount = [dbManager getUnreadMessageCount];
    dispatch_async(dispatch_get_main_queue(), ^{
        // set unread badge
    });
}

- (NSMutableArray *)getConversations {
	if (!m_Conversations) {
		m_Conversations = [[NSMutableArray alloc] init];
		[self performSelectorInBackground:@selector(loadConversations) withObject:nil];
	}
	return m_Conversations;
}

- (NSMutableArray *)getConversation:(NSMutableArray *)arrayList fromPhone:(NSString *)fromPhone {
	if (!arrayList) {
        return nil;
	}
	
	[dbManager getConversation:arrayList :fromPhone];
	[self performSelectorInBackground:@selector(markConversationAsRead:) withObject:fromPhone];
	return arrayList;
}


- (NSMutableArray *)getRecentCalls {
	if (!m_RecentCalls) {
		m_RecentCalls = [[NSMutableArray alloc] init];
		[self performSelectorInBackground:@selector(loadRecentCalls) withObject:nil];
	}
	return m_RecentCalls;
}

- (void)clearRecentCalls {
    [dbManager clearAllRecentCalls];
    [self performSelectorInBackground:@selector(loadRecentCalls) withObject:nil];
}

- (void)reloadContacts {
	if (!contacts) {
		contacts = [[NSMutableArray alloc] init];
	}
	
	[self performSelectorInBackground:@selector(loadContacts) withObject:nil];
}

- (void)reloadConversations {
	if (!m_Conversations) {
		m_Conversations = [[NSMutableArray alloc] init];
	}
	
	[self performSelectorInBackground:@selector(loadConversations) withObject:nil];
}

- (void)reloadConversationsFromDatabase {
	if (!m_Conversations) {
		m_Conversations = [[NSMutableArray alloc] init];
		[self performSelectorInBackground:@selector(loadConversations) withObject:nil];
		return;
	}
	[self getConversationsFromDatabase:NO];
}

- (void)reloadRecentCalls {
	if (!m_RecentCalls) {
		m_RecentCalls = [[NSMutableArray alloc] init];
	}
	
	[self performSelectorInBackground:@selector(loadRecentCalls) withObject:nil];
}

- (void)cleanCountriesList {
	if (countries) {
		[countries release];
	}
}

- (void)updateMyLocation {
	RequestData *request = [[RequestData alloc] init];
	request.url = URL_LOCATION;
	request.headers = [[NSMutableDictionary alloc] init];
	request.parameters = @"";
	request.type = kGet;
	request.serviceTag = 1001;
	request.timeOut = 10;
	[proxy performHttpPostRequest:request :self];
	[request release];
	
}

- (void)sendDeviceToken {
    if ([[settings getUserName] length] == 0) {
        return;
    }
    
    RequestData *request = [[RequestData alloc] init];
	request.url = URL_DEVICETOKEN;
	request.headers = [[NSMutableDictionary alloc] init];

	NSString *urlString = [@""stringByAppendingString:@"task=register"];
    
    UIDevice *dev = [UIDevice currentDevice];
	NSString *deviceUuid = dev.uniqueIdentifier;
    NSString *deviceName = dev.name;
	NSString *deviceModel = dev.model;
	NSString *deviceSystemVersion = dev.systemVersion;
    
	urlString = [urlString stringByAppendingString:@"&appname=jmobi"];
	urlString = [urlString stringByAppendingString:@"&appversion=1.0"];
	urlString = [urlString stringByAppendingString:@"&deviceuid="];
	urlString = [urlString stringByAppendingString:deviceUuid];
	urlString = [urlString stringByAppendingString:@"&devicetoken="];
	urlString = [urlString stringByAppendingString:[settings getDeviceToken]];
	urlString = [urlString stringByAppendingString:@"&devicename="];
	urlString = [urlString stringByAppendingString:deviceName];
	urlString = [urlString stringByAppendingString:@"&devicemodel="];
	urlString = [urlString stringByAppendingString:deviceModel];
	urlString = [urlString stringByAppendingString:@"&deviceversion="];
	urlString = [urlString stringByAppendingString:deviceSystemVersion];
	urlString = [urlString stringByAppendingString:@"&pushbadge=enabled"];
	urlString = [urlString stringByAppendingString:@"&pushalert=enabled"];
	urlString = [urlString stringByAppendingString:@"&pushsound=enabled"];
    urlString = [urlString stringByAppendingString:@"&vn="];
    urlString = [urlString stringByAppendingString:[settings getUserName]];
	request.parameters = urlString;
	request.type = kGet;
	request.serviceTag = 1000;
	request.timeOut = 10;
    [proxy performHttpPostRequest:request];
	[request release];
}

- (void)registerPhone:(NSString *)phoneNumber {
	NSLog(@"Register Request");
	RequestData *request = [[RequestData alloc] init];
	request.url = URL_REGISTERPHONE;
	request.headers = [[NSMutableDictionary alloc] init];
	request.parameters = [NSString stringWithFormat:@"Action=GETPIN&GSM=%@&UDID=%@&CC=%@&DEVICETOKEN=%@",
                          phoneNumber,
						  [settings getDeviceToken],
						  [settings getMyLocationCode],
                          [settings getDeviceToken]];
	request.type = kGet;
	request.timeOut = 10;
	request.serviceTag = 1002;
	[proxy performHttpPostRequest:request :self];
	[request release];	
}

- (void)registerPhone:(NSString *)phoneNumber withExistingVirtualNumber:(NSString *)virtualNumber {
    //Action=GETPINEXISTING&GSM=447733488488&VN=441481898004
    NSLog(@"Register Request");
	RequestData *request = [[RequestData alloc] init];
	request.url = URL_REGISTERPHONE;
	request.headers = [[NSMutableDictionary alloc] init];
	request.parameters = [NSString stringWithFormat:@"Action=GETPINEXISTING&GSM=%@&VN=%@",
                          phoneNumber,
                          virtualNumber];
	request.type = kGet;
	request.timeOut = 10;
	request.serviceTag = 1002;
	[proxy performHttpPostRequest:request :self];
	[request release];
}

- (void)verifyCode:(NSString *)passCode {
	RequestData *request = [[RequestData alloc] init];
	request.url = URL_VERIFYCODE;
	request.headers = [[NSMutableDictionary alloc] init];
	request.parameters = [NSString stringWithFormat:@"Action=GETVN&UDID=%@&GSM=%@&PIN=%@&DEVICETOKEN=%@",
                          [settings getDeviceToken],
						  [settings getUserName],
						  passCode,
                          [settings getDeviceToken]];
	request.type = kGet;
	request.timeOut = 10;
	request.serviceTag = 1003;
	[proxy performHttpPostRequest:request :self];
	[request release];	
}

- (void)sendText:(NSString *)to :(NSString *)message {
	RequestData *request = [[RequestData alloc] init];
	request.url = URL_SENDTEXT;
	request.headers = [[NSMutableDictionary alloc] init];
	request.parameters = [NSString stringWithFormat:@"mode=send&phone=%@&pass=%@&to=%@&msg_text=%@",
						  [settings getUserName],
						  [settings getPassword],
						  to,
						  message];
	request.type = kGet;
	request.timeOut = 10;
	request.serviceTag = 1004;
	[proxy performHttpPostRequest:request :self];
	[request release];
}

- (void)getTextMessagesFromServer:(NSString *)pageNumber {
	RequestData *request = [[RequestData alloc] init];
	request.url = URL_SENDTEXT;
	request.headers = [[NSMutableDictionary alloc] init];
	request.parameters = [NSString stringWithFormat:@"mode=get&phone=%@&pass=%@&page=%@",
						  [settings getUserName],
						  [settings getPassword],
						  pageNumber];
	request.type = kGet;
	request.serviceTag = 1006;
	[proxy performHttpPostRequest:request :self];
	[request release];
}

- (void)getRecentCallsFromServer {
    RequestData *request = [[RequestData alloc] init];
	request.url = URL_MISSEDCALLSERVICE;
	request.headers = [[NSMutableDictionary alloc] init];
	request.parameters = [NSString stringWithFormat:@"mode=get_missed_calls&phone=%@&pass=%@",
						  [settings getUserName],
						  [settings getPassword]];
	request.type = kGet;
	request.serviceTag = 1010;
	[proxy performHttpPostRequest:request :self];
	[request release];
}
#pragma mark -
#pragma mark WebProxy Delegate

- (void)webProxyDidFinishRequest:(RequestData *)request {
	NSLog(@"Result: %@", request.result);
	NSLog(@"HTTP Response Headers %@", request.headers);

	switch (request.serviceTag) {
		case 1001:
			[self workOnLocationResponse:request.result];
			break;
		case 1002:
			if (![[request.headers objectForKey:@"StatusCode"] isEqual:@"200"]) {
				request.result = [NSMutableString stringWithString:APP_CONNECTION_ERROR];
			}
            if ([request.result length] == 8) {
                [self workOnRegisterResponse:request.result :@"Success"];
            } else {
                [self workOnRegisterResponse:request.result :@"Failed"];
            }
			break;
		case 1003:
			if (![[request.headers objectForKey:@"StatusCode"] isEqual:@"200"]) {
				request.result = [NSMutableString stringWithString:APP_CONNECTION_ERROR];
			}
			[self workOnPasscodeResponse:request.result :[request.headers objectForKey:@"Result"]];
			break;
		case 1004:
			if (![[request.headers objectForKey:@"StatusCode"] isEqual:@"200"]) {
				request.result = [NSMutableString stringWithString:APP_CONNECTION_ERROR];
			}
			[self workOnSendTextResponse:request.result :[request.headers objectForKey:@"Result"]];
			break;
		case 1006:
			[self workOnGetTextMessagesResponse:request.result :[request.headers objectForKey:@"Result"]];
			break;
		case 1007:
			[self workOnRegisteredContactsResponse:request.result :[request.headers objectForKey:@"Result"]];
			break;
        case 1010:
			[self workOnRecentCallsResponse:request.result :[request.headers objectForKey:@"Result"]];
			break;    
		default:
			break;
	}
}

#pragma mark -
#pragma mark Response Parsing

- (void)workOnLocationResponse:(NSString *)responseString {
	if (!responseString || [responseString length] == 0) {
		dispatch_async(dispatch_get_main_queue(), ^{
			[[NSNotificationCenter defaultCenter] postNotificationName:@"RegistrationCallback" object:@"LocationFailed"];
		});
		return;
	}
	Country *country = [[Country alloc] init];
	
	if ([dbManager getCountry:country :responseString]) {
		[settings setMyLocation:country.countryName];
		[settings setMyLocationCode:country.dialingCode];
		NSLog(@"%@", country.countryName);
	}

	[country release];
	dispatch_async(dispatch_get_main_queue(), ^{
		[[NSNotificationCenter defaultCenter] postNotificationName:@"RegistrationCallback" object:nil];
	});
}

- (void)workOnRegisterResponse:(NSString *)responseString :(NSString *)result {
	dispatch_async(dispatch_get_main_queue(), ^{
		NSLog(@"Dispatching Register Notification");
		if ([result isEqualToString:@"Success"]) {
			[[NSNotificationCenter defaultCenter] postNotificationName:@"RegistrationCallback" object:@"Registered"];
		} else {
			[[NSNotificationCenter defaultCenter] postNotificationName:@"RegistrationCallback" object:responseString];
		}
	});
}

- (void)workOnPasscodeResponse:(NSString *)responseString :(NSString *)result {
	dispatch_async(dispatch_get_main_queue(), ^{
        if ([responseString rangeOfString:@"VN="].length > 0) {
            NSArray *components = [responseString componentsSeparatedByString:@","];
            if ([components count] == 2) {
                [settings setGSMNumber:[settings getUserName]];
                [settings setUserName:[[components objectAtIndex:0] stringByReplacingOccurrencesOfString:@"VN=" withString:@""]];
                [settings setPassword:[[components objectAtIndex:1] stringByReplacingOccurrencesOfString:@"PASSCODE=" withString:@""]];
                [self sendDeviceToken];
                [[NSNotificationCenter defaultCenter] postNotificationName:@"PasscodeCallback" object:@"Registered"];
            }
        } else if ([responseString rangeOfString:@"EXIST"].length > 0) {
            NSArray *components = [responseString componentsSeparatedByString:@"<"];
            if ([components count] == 2) {
                [settings setGSMNumber:[settings getUserName]];
                [settings setUserName:[[components objectAtIndex:0] stringByReplacingOccurrencesOfString:@"EXIST=" withString:@""]];
                [settings setPassword:@"123"];
                [[NSNotificationCenter defaultCenter] postNotificationName:@"PasscodeCallback" object:@"Registered"];
            }
        } else {
            [[NSNotificationCenter defaultCenter] postNotificationName:@"PasscodeCallback" object:responseString];
        }
	});
}

- (void)workOnSendTextResponse:(NSString *)responseString :(NSString *)result {
	dispatch_async(dispatch_get_main_queue(), ^{
		if ([result isEqualToString:@"Success"]) {
			[[NSNotificationCenter defaultCenter] postNotificationName:@"Messaging" object:responseString];
			[self reloadConversations];
		} else {
			[[NSNotificationCenter defaultCenter] postNotificationName:@"Messaging" object:responseString];
		}
	});
}

- (void)workOnGetTextMessagesResponse:(NSString *)responseString :(NSString *)result {
	//NSLog(@"TextMessages: %@", responseString);
	//"sms_from":"923224005459","sms_text":"V2Fzc3VwLi4u","sms_date":"2011-02-23 11:37:09","sms_read":"n"
	SBJSON *parser = [[SBJSON alloc] init];
	NSDictionary *object = [parser objectWithString:responseString error:nil];
    [parser release];
	if ([object isKindOfClass:[NSDictionary class]] && [object objectForKey:@"data"]) {
		
	}
	else {
		BOOL bNeedsRefresh = NO;
		for (NSDictionary *status in object)
		{
			NSString *strMessage = [NSString stringWithFormat:@"%@", [status objectForKey:@"sms_text"]];
			NSData *messageData = [NSData dataWithBase64String:strMessage];
			strMessage = [[[NSString alloc] initWithData:messageData encoding:NSUTF8StringEncoding]autorelease];
			NSLog(@"%@: %@", [status objectForKey:@"sms_from"], strMessage);
			NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
			NSTimeZone *gmt = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
			[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:SS +0000"];
			[dateFormatter setTimeZone:gmt];	
			//NSDate *serverDate = [[NSDate alloc] init];
			NSDate *serverDate = [dateFormatter dateFromString:[NSString stringWithFormat:@"%@ +0000", [status objectForKey:@"sms_date"]]];
			if (!serverDate) {
				serverDate = [NSDate date];
			}
			
			//NSLog(@"%@", [serverDate description]);
            [dateFormatter release];
			BOOL bInserted = [dbManager addTextMessage:[status objectForKey:@"sms_from"]
													  :strMessage
													  :serverDate 
													  :[[status objectForKey:@"sms_read"] isEqualToString:@"n"]?NO:YES
													  :[status objectForKey:@"sms_id"]
													  :[status objectForKey:@"sms_to"]
													  :[[status objectForKey:@"sms_type"] isEqualToString:@"inbox"]?0:1];		
			if (!bInserted) {
				break;
			} else {
				if (!bNeedsRefresh) {
					bNeedsRefresh = YES;
				}
			}

		}
		
		if (bNeedsRefresh) {
			[self getConversationsFromDatabase:NO];
		}		
	}
}

- (void)workOnRegisteredContactsResponse:(NSString *)responseString :(NSString *)result {
	NSArray *recordsArray = [responseString componentsSeparatedByString:@","];
	[dbManager clearSipPhoneNumbers];
    //NSLog(@"ResponseString: %@", responseString);
	BOOL bShouldUpdateContacts = NO;
	for (int i = 0; i < [recordsArray count]; i++) {
		NSArray *columnArray = [[recordsArray objectAtIndex:i] componentsSeparatedByString:@"|"];
        //NSLog(@"ColumnArray: %@", columnArray);
        if ([columnArray count] > 1) {
            NSArray *phoneNumbers = [ABContactsHelper contactsMatchingPhone:[columnArray objectAtIndex:1]];
            if ([phoneNumbers count] == 0) {
                NSString *strOriginalPhoneNumber = [columnArray objectAtIndex:1];
                if ([strOriginalPhoneNumber characterAtIndex:0] == ' ') {
                    strOriginalPhoneNumber = [strOriginalPhoneNumber stringByReplacingCharactersInRange:NSRangeFromString(@"0,1") withString:@"+"];
                    //NSLog(@"Original Number: %@", strOriginalPhoneNumber);
                    phoneNumbers = [ABContactsHelper contactsMatchingPhone:strOriginalPhoneNumber];
                }
            }
            if ([phoneNumbers count] > 0) {
                //NSLog(@"Name: %@", ((ABContact *)[phoneNumbers objectAtIndex:0]).compositeName);
                BOOL retValue = [dbManager addSipPhoneNumbers:[NSString stringWithFormat:@"%d", ((ABContact *)[phoneNumbers objectAtIndex:0]).recordID] strPhoneNumber:[columnArray objectAtIndex:1] strSipNumber:[columnArray objectAtIndex:0]];
                if (!bShouldUpdateContacts) {
                    bShouldUpdateContacts = retValue;
                }
            }
            //NSLog(@"Registered contacts are: %@", columnArray);
        }
	}
	if (bShouldUpdateContacts) {
		NSLog(@"New sip contacts found, now reloading contacts");
		[self getContactsFromDatabase];
	}
	m_bContactListSent = YES;
    [settings setLastRegisteredUsersUpdated:[[NSDate date] timeIntervalSince1970]];
}

- (void)workOnRecentCallsResponse:(NSString *)responseString :(NSString *)result {
    SBJSON *parser = [[SBJSON alloc] init];
	NSDictionary *object = [parser objectWithString:responseString error:nil];
    [parser release];
    
    if ([object isKindOfClass:[NSDictionary class]] && [object objectForKey:@"data"]) {
		return;
	}
    
    BOOL bRefreshNeeded = NO;
    
    for (NSDictionary *status in object)
    {
        NSString *strCallTime = [NSString stringWithFormat:@"%@", [status objectForKey:@"call_time"]];
        NSString *strCallerId = [NSString stringWithFormat:@"%@", [status objectForKey:@"call_from"]];
        
        RecentCallItem *item = [[RecentCallItem alloc] init];
        
        item.CallType = 1;
        item.CallTime = [strCallTime doubleValue];
        item.PhoneNumber = strCallerId;
        item.Duration = 0;
        
        if ([dbManager addRecentCallItem:item])
            bRefreshNeeded = YES;
        
        [item release];
        item = nil;
    }
    
    if (bRefreshNeeded)
        [self reloadRecentCalls];
}

#pragma mark -
#pragma mark Private

- (void)loadConversations {
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	[self getConversationsFromDatabase:NO];
	[self getTextMessagesFromServer:@"0"];
	[pool release];
}

- (void)loadRecentCalls {
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	[[NSNotificationCenter defaultCenter] postNotificationName:@"RecentCalls" object:@"wait"];
	[dbManager getRecentCalls:m_RecentCalls bMissedOnly:[settings getRecentCallsSelected] == 0 ? NO : YES];
	dispatch_async(dispatch_get_main_queue(), ^{
		[[NSNotificationCenter defaultCenter] postNotificationName:@"RecentCalls" object:@"reload"];
	});
	[pool release];
}

- (void)loadContacts {
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	if (![settings getIsPhoneBookAccessGranted]) {
		[contacts removeAllObjects];
		[pool release];
		return;
	}
	
	[self getContactsFromDatabase];
	
	ABAddressBookRef *addressBook = (ABAddressBookRef *) ABAddressBookCreate();
	
	CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
	CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
	BOOL bUpdateNeeded = NO;
	for (int i = 0; i < nPeople; i++) {
		ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
		if(person != nil){
			PhoneContact *contact = [[PhoneContact alloc] init];
			[contact setValue:[NSString stringWithFormat:@"%d", ABRecordGetRecordID(person)] forKey:@"Id"];
			
			contact.FirstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
			contact.LastName = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
			contact.IsSipUser = NO;
			
			if([dbManager addContact:contact])
				bUpdateNeeded = YES;
			
			[contact release];
            contact = nil;
		}
        CFRelease(person);
	}
	[settings setInitialPhoneBookSyncCompleted:YES];
	
	CFRelease(addressBook);	
	
	if(bUpdateNeeded) {
		NSLog(@"New Contacts added in the database... now sending contacts to server");
		[self getContactsFromDatabase];
        [self performSelectorInBackground:@selector(getRegisteredContactsFromServer) withObject:nil];
	} else {
        NSDate *date = [NSDate dateWithTimeIntervalSince1970:[settings getLastRegisteredUsersUpdated]];
        
        NSTimeInterval secondsBetween = [[NSDate date] timeIntervalSinceDate:date];
        
        int numberOfDays = secondsBetween / 86400;
        
        if (numberOfDays > 0) {
            [self performSelectorInBackground:@selector(getRegisteredContactsFromServer) withObject:nil];
        }
    }
	
	[pool release];
}

- (void)getContactsFromDatabase {
	dispatch_async(dispatch_get_main_queue(), ^{
		[[NSNotificationCenter defaultCenter] postNotificationName:@"Contacts" object:@"wait" userInfo:nil];
	});
	
	[contacts removeAllObjects];
	[dbManager getContacts:contacts bVoxperOnly:[settings getContactsGroupSelected] == 0 ? NO : YES];

	dispatch_async(dispatch_get_main_queue(), ^{
		[[NSNotificationCenter defaultCenter] postNotificationName:@"Contacts" object:@"reload" userInfo:nil];
	});
}

- (void)getConversationsFromDatabase:(BOOL)bSilently {
    // silently means there's no need to update tableview or notify UI
    // this will simply reload data;
    if (bSilently) {
        [m_Conversations removeAllObjects];
        [dbManager getConversations:m_Conversations :[settings getUserName]];
        //int nUnreadCount = [dbManager getUnreadMessageCount];
        dispatch_async(dispatch_get_main_queue(), ^{
//            if (nUnreadCount == 0)
//                [[app.TabbarController.tabBar.items objectAtIndex:0] setBadgeValue:nil];
//            else
//                [[app.TabbarController.tabBar.items objectAtIndex:0] setBadgeValue:[NSString stringWithFormat:@"%d", nUnreadCount]];
        });
        return;
    }
    
	dispatch_async(dispatch_get_main_queue(), ^{
		[[NSNotificationCenter defaultCenter] postNotificationName:@"Conversation" object:@"wait"];
	});
    
	[m_Conversations removeAllObjects];
	[dbManager getConversations:m_Conversations :[settings getUserName]];
	
	dispatch_async(dispatch_get_main_queue(), ^{
		[[NSNotificationCenter defaultCenter] postNotificationName:@"Conversation" object:@"reload"];
	});
    
    //int nUnreadCount = [dbManager getUnreadMessageCount];
    dispatch_async(dispatch_get_main_queue(), ^{
//        if (nUnreadCount == 0)
//            [[app.TabbarController.tabBar.items objectAtIndex:0] setBadgeValue:nil];
//        else
//            [[app.TabbarController.tabBar.items objectAtIndex:0] setBadgeValue:[NSString stringWithFormat:@"%d", nUnreadCount]];
    });
}

- (void)getRegisteredContactsFromServer {
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	if ([[settings getUserName] length] < 1) {
		[pool release];
		return;
	}
    
	if (!m_bContactListSent) {
		ABAddressBookRef *addressBook = (ABAddressBookRef *) ABAddressBookCreate();
		
		CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
		CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
		NSString *strContacts = @"";
		for (int i = 0; i < nPeople; i++) {
			ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
			if (person) {
				PhoneContact *contact = [[PhoneContact alloc] init];
				[contact setValue:[NSString stringWithFormat:@"%d", ABRecordGetRecordID(person)] forKey:@"Id"];
				
				contact.FirstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
				contact.LastName = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
				strContacts = [NSString stringWithFormat:@"%@%@%@", strContacts, @",", [[ABRecordReader personContactNumbers:person] componentsJoinedByString:@","]];
                [contact release];
                contact = nil;
			}
		}
		
		RequestData *request = [[RequestData alloc] init];
		request.url = URL_CONTACTSERVICE;
		request.headers = [[NSMutableDictionary alloc] init];
		[request.headers setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"];
		request.parameters = [NSString stringWithFormat:@"mode=check_contacts&phone=%@&pass=%@&contacts=%@",
							  [settings getUserName],
							  [settings getPassword],
							  strContacts];
		request.type = kPost;
		request.serviceTag = 1007;
		[proxy performHttpPostRequest:request :self];
		[request release];
		
		CFRelease(addressBook);
	}
	[pool release];
}

- (void)markConversationAsRead:(id)fromPhone {
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	[dbManager markConversationAsRead:(NSString *)fromPhone];
    [self getConversationsFromDatabase:YES];
	// TODO: Do HTTP Hit to make this conversation marked as read.
    
//	RequestData *request = [[RequestData alloc] init];
//	request.url = URL_CONTACTSERVICE;
//	request.headers = [[NSMutableDictionary alloc] init];
//	[request.headers setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"];
//	request.parameters = [NSString stringWithFormat:@"mode=check_contacts&phone=%@&pass=%@&contacts=%@",
//						  [settings getUserName],
//						  [settings getPassword],
//						  strContacts];
//	request.type = kPost;
//	request.serviceTag = 1007;
//	[proxy performHttpPostRequest:request :self];
//	[request release];
	[pool release];
}

- (void)addRecentCallAndReload:(RecentCallItem *)recentCallItem {
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    [recentCallItem retain];
	[dbManager addRecentCallItem:recentCallItem];
	[self reloadRecentCalls];
    [recentCallItem release];
	[pool release];
}

- (void)deleteConversationFromServer:(NSString *)strPhoneNumber {
	RequestData *request = [[RequestData alloc] init];
	request.url = URL_SMSDELSERVICE;
	request.headers = [[NSMutableDictionary alloc] init];
	[request.headers setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"];
	request.parameters = [NSString stringWithFormat:@"mode=delete_conversation&phone=%@&pass=%@&num=%@",
						  [settings getUserName],
						  [settings getPassword],
						  strPhoneNumber];
	request.type = kPost;
    // we don't need to parse the response...
    [proxy performHttpPostRequest:request];
	request.serviceTag = 1008;
	[request release];

}

#pragma mark -
#pragma mark General Purpose Functions

- (NSString *)convertPhoneNumberInIntlFormat:(NSString *)strPhone :(BOOL)bAppendCountry {
	strPhone = [strPhone stringByReplacingOccurrencesOfRegex:@"[^+0-9]" withString:@""];
	NSString *strPhoneNumber = nil;
	if ([strPhone hasPrefix:@"0011"]) {
		strPhoneNumber = [strPhone substringFromIndex:4];
	} else if ([strPhone hasPrefix:@"00"]) {
		strPhoneNumber = [strPhone substringFromIndex:2];
	} else if ([strPhone hasPrefix:@"+"]) {
		if ([strPhone hasPrefix:@"+11"]) {
			strPhoneNumber = [strPhone substringFromIndex:3];
		} else {
			strPhoneNumber = [strPhone substringFromIndex:1];
		}
	} else if ([strPhone hasPrefix:@"011"]) {
		strPhoneNumber = [strPhone substringFromIndex:3];
	} else if ([strPhone hasPrefix:@"0"]) {
		strPhoneNumber = [strPhone substringFromIndex:1];
		strPhoneNumber = [NSString stringWithFormat:@"%@%@", [app.uiManager.settings getMyLocationCode], strPhoneNumber];
	} else {
		if (![strPhone hasPrefix:[app.uiManager.settings getMyLocationCode]] && bAppendCountry) {
			strPhoneNumber = [NSString stringWithFormat:@"%@%@", [app.uiManager.settings getMyLocationCode], strPhone];
		} else {
			strPhoneNumber = strPhone;
		}

	}
	
	NSLog(@"UIManager::ConvertPhoneNumberInIntlFormat-> Result: %@", strPhoneNumber);
	return strPhoneNumber;
}

- (NSString *)makePhoneNumberInIntlFormat:(NSString *)strPhone {
	strPhone = [strPhone stringByReplacingOccurrencesOfRegex:@"[^+0-9]" withString:@""];
	
	NSString *strPhoneNumber = nil;
	
	if ([strPhone hasPrefix:@"0011"]) {
		strPhoneNumber = strPhone;
	} else if ([strPhone hasPrefix:@"00"]) {
		strPhoneNumber = strPhone;
	} else if ([strPhone hasPrefix:@"+"]) {
		strPhoneNumber = strPhone;
	} else if ([strPhone hasPrefix:@"011"]) {
		strPhoneNumber = strPhone;
	} else if ([strPhone hasPrefix:@"0"]) {
		strPhoneNumber = [strPhone substringFromIndex:1];
		strPhoneNumber = [NSString stringWithFormat:@"+%@%@", [app.uiManager.settings getMyLocationCode], strPhoneNumber];
	} else {
		if (![strPhone hasPrefix:[app.uiManager.settings getMyLocationCode]]) {
			strPhoneNumber = [NSString stringWithFormat:@"+%@%@", [app.uiManager.settings getMyLocationCode], strPhone];
		} else {
			strPhoneNumber = [NSString stringWithFormat:@"+%@", strPhone];
		}
		
	}
	
	NSLog(@"UIManager::ConvertPhoneNumberInIntlFormat-> Result: %@", strPhoneNumber);
	return strPhoneNumber;
}

- (void)setContactsGroupSelection:(int)nSelectedIndex {
	[settings setContactsGroupSelected:nSelectedIndex];
	[self getContactsFromDatabase];
}

- (void)setRecentCallsSelection:(int)nSelectedIndex {
	[settings setRecentCallsSelected:nSelectedIndex];
	[self loadRecentCalls];
}


- (NSString *)getPrettyDate:(NSDate *)_date {
    NSString *strReturnValue = @"";
    NSTimeInterval secondsBetween = [[NSDate date] timeIntervalSinceDate:_date];
    
    int numberOfDays = secondsBetween / 86400;
    
    switch (numberOfDays) {
        case 0:
        {
            NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
            [dateFormat setDateFormat:@"h:mm a"];
            NSString *dateString = [dateFormat stringFromDate:_date];
            strReturnValue = dateString;
            [dateFormat release];
            break;
        }
        case 1:
            strReturnValue = @"Yesterday";
            break;
        case 2:
        case 3:
        case 4:
        case 5:
        case 6:
        {
            NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
            [dateFormatter setDateFormat:@"EEEE"];
            strReturnValue = [dateFormatter stringFromDate:_date];
            [dateFormatter release];
        }
            break;
        default:
        {
            NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
            [dateFormatter setDateFormat:@"MMM dd,yy"];
            strReturnValue = [dateFormatter stringFromDate:_date];
            [dateFormatter release];
        }
            break;
    }
    
    //NSLog(@"There are %d days in between the two dates.", numberOfDays);
    return strReturnValue;
}

- (ABRecordRef)buildUnknownContactDetails:(NSString *)strPhoneNumber {
    ABRecordRef person = ABPersonCreate(); 
    CFErrorRef  error = NULL;  
    
    ABRecordSetValue(person, kABPersonFirstNameProperty, strPhoneNumber, NULL);
    
    // email
    ABMutableMultiValueRef email = ABMultiValueCreateMutable(kABMultiStringPropertyType);
    ABMultiValueAddValueAndLabel(email, strPhoneNumber, kABPersonPhoneMainLabel, NULL);
    ABRecordSetValue(person, kABPersonPhoneProperty, email, &error);
    CFRelease(email); 
    
    if (error != NULL) 
        NSLog(@"Error: %@", error);
    
    [(id)person autorelease];
    return person;
}

- (void)handleApplicationDidFinishedLaunchingWithOptions:(NSDictionary *)launchOptions {
    if ([settings shouldDisplaySplashView]) {
        SplashViewController *splashViewController = [[SplashViewController alloc] initWithNibName:@"SplashViewController" bundle:[NSBundle mainBundle]];
        [app setNavigationController:[[UINavigationController alloc] initWithRootViewController:splashViewController]];
		[app.window addSubview:[app.NavigationController view]];
		
		[splashViewController release];
        return;
    }
    
    if ([[settings getUserName] length] == 0 || [[settings getPassword] length] == 0) {
        // user/password not configured
        RegistrationOptionsViewController *regOptionsViewController = [[RegistrationOptionsViewController alloc] initWithNibName:@"RegistrationOptionsViewController" bundle:[NSBundle mainBundle]];
        [app setNavigationController:[[UINavigationController alloc] initWithRootViewController:regOptionsViewController]];
		[app.window addSubview:[app.NavigationController view]];
        
        [regOptionsViewController release];
    } else {
        // settings configured
        [app initiateUI];
        NSLog(@"Received Notification (Launch): %@", [[launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"] objectForKey:@"aps"]);

        if (launchOptions)
		{
			if ([launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"])
			{
				if ([[launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"] objectForKey:@"aps"])
				{
					NSLog(@"Received Notification (Launch): %@", [[launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"] objectForKey:@"aps"]);
                    
					NSString *strMessage = [NSString stringWithFormat:@"%@", [[[launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"] objectForKey:@"aps"] objectForKey:@"alert"]];
					
                    if ([strMessage rangeOfString:@"Incoming Call"].length > 0) {
						NSLog(@"%@", strMessage);
						strMessage = [strMessage substringFromIndex:[strMessage rangeOfString:@"Incoming call from"].length];
						NSLog(@"%@", strMessage);
						[self launchAnswerScreen:@"Answering Call"];
					} else if ([strMessage rangeOfString:@"pin code"].length > 0) {
                    } else if ([strMessage hasPrefix:@"New SMS"]){
					} else {
					}
				}
			}
        }
    }
}

@end